

<template>
  <div class="app-container">
    <div class="left-box">
      <draggable
        :list="componentsList"
        :group="{ name: 'people', pull: 'clone', put: false }"
        :move="move"
        item-key="id"
        class="parent-flex"
      >
        <template #item="{ element }">
          <div class="componentsItem">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
    <div class="content-box">
      <el-scrollbar style="height: 100%">
        <div class="layout">
          <el-row :gutter="20">
            <draggable
              v-model="dataForm.components"
              animation="300"
              chosenClass="drag-chosen"
              ghostClass="drag-ghost"
              group="people"
              :scroll="true"
              handle=".mover"
              class="drag-out-class"
              item-key="id"
              @add="add"
              @end="end"
              @choose="choose"
              @change="update"
            >
              <template #item="{ element, index }">
                <el-col
                  :span="element.colSpan"
                  class="colSpan"
                  :class="{ move: curIndex == index }"
                  @click.stop.prevent="handleItem(index)"
                >
                  <div
                    class="deleteBtn"
                    @click.stop.prevent="handleDelete(index)"
                    v-show="curIndex == index"
                  >删除</div>
                  <div v-if="element.type == 'Input'">
                    <InputView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'InputNumber'">
                    <InputNumberView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'TextArea'">
                    <TextAreaView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'SelectRadio'">
                    <SelectRadioView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'SelectMultiple'">
                    <SelectMultipleView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'ButtonRadio'">
                    <ButtonRadioView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'ButtonCheckbox'">
                    <ButtonCheckboxView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'DatePicker'">
                    <DatePickerView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'DateRange'">
                    <DateRangeView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'Cascader'">
                    <CascaderView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'UploadFile'">
                    <UploadFileView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'UploadImage'">
                    <UploadImageView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'Switch'">
                    <SwitchView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                  <div v-if="element.type == 'Slider'">
                    <SliderView :childData="element" :formParams="dataForm.formParams" />
                  </div>
                </el-col>
              </template>
            </draggable>
          </el-row>
        </div>
      </el-scrollbar>
      <div class="btns">
        <el-button type="primary" @click="handlePreview">预览效果</el-button>
        <!-- <el-button type="primary" @click="handleCreate">代码生成</el-button> -->
        <el-button type="primary" @click="handleImport">单表导入</el-button>
      </div>
    </div>
    <div class="right-box">
      <el-tabs v-model="rightActive">
        <el-tab-pane label="组件属性" name="component">
          <div class="rightBox">
            <el-scrollbar style="height: 80%">
              <el-form :model="dataForm" label-width="100px" label-position="top">
                <div
                  class="rightItem"
                  v-for="(item, index) in dataForm.components"
                  v-show="curIndex == index"
                  :key="index"
                >
                  <InputSet :childData="item" v-if="item.type == 'Input'" />
                  <InputNumberSet :childData="item" v-if="item.type == 'InputNumber'" />
                  <TextAreaSet :childData="item" v-if="item.type == 'TextArea'" />
                  <SelectRadioSet :childData="item" v-if="item.type == 'SelectRadio'" />
                  <SelectMultipleSet :childData="item" v-if="item.type == 'SelectMultiple'" />
                  <ButtonRadioSet :childData="item" v-if="item.type == 'ButtonRadio'" />
                  <ButtonCheckboxSet :childData="item" v-if="item.type == 'ButtonCheckbox'" />
                  <DatePickerSet :childData="item" v-if="item.type == 'DatePicker'" />
                  <DateRangeSet :childData="item" v-if="item.type == 'DateRange'" />
                  <CascaderSet :childData="item" v-if="item.type == 'Cascader'" />
                  <UploadFileSet :childData="item" v-if="item.type == 'UploadFile'" />
                  <UploadImageSet :childData="item" v-if="item.type == 'UploadImage'" />
                  <SwitchSet :childData="item" v-if="item.type == 'Switch'" />
                  <SliderSet :childData="item" v-if="item.type == 'Slider'" />
                </div>
              </el-form>
            </el-scrollbar>
          </div>
        </el-tab-pane>
        <el-tab-pane label="表单属性" name="form">
          <FormSet :dataForm="dataForm.formParams" />
        </el-tab-pane>
      </el-tabs>
    </div>
    <CodePreview ref="CodePreviewRef" v-if="isCodePreview" @close="isCodePreview=false" />
    <EntitySelect
      ref="EntitySelectRef"
      v-if="isEntitySelect"
      @close="isEntitySelect=false"
      @update="entitySelect"
    />
  </div>
</template>
<script setup>
import draggable from "vuedraggable";

import FormSet from "./componentSet/FormSet.vue";

import InputView from "./componentView/Input.vue";
import InputSet from "./componentSet/Input.vue";

import InputNumberView from "./componentView/InputNumber.vue";
import InputNumberSet from "./componentSet/InputNumber.vue";

import TextAreaView from "./componentView/TextArea.vue";
import TextAreaSet from "./componentSet/TextArea.vue";

import SelectRadioView from "./componentView/SelectRadio.vue";
import SelectRadioSet from "./componentSet/SelectRadio.vue";

import SelectMultipleView from "./componentView/SelectMultiple.vue";
import SelectMultipleSet from "./componentSet/SelectMultiple.vue";

import ButtonRadioView from "./componentView/ButtonRadio.vue";
import ButtonRadioSet from "./componentSet/ButtonRadio.vue";

import ButtonCheckboxView from "./componentView/ButtonCheckbox.vue";
import ButtonCheckboxSet from "./componentSet/ButtonCheckbox.vue";

import DatePickerView from "./componentView/DatePicker.vue";
import DatePickerSet from "./componentSet/DatePicker.vue";

import DateRangeView from "./componentView/DateRange.vue";
import DateRangeSet from "./componentSet/DateRange.vue";

import CascaderView from "./componentView/Cascader.vue";
import CascaderSet from "./componentSet/Cascader.vue";

import UploadFileView from "./componentView/UploadFile.vue";
import UploadFileSet from "./componentSet/UploadFile.vue";

import UploadImageView from "./componentView/UploadImage.vue";
import UploadImageSet from "./componentSet/UploadImage.vue";

import SwitchView from "./componentView/Switch.vue";
import SwitchSet from "./componentSet/Switch.vue";

import SliderView from "./componentView/Slider.vue";
import SliderSet from "./componentSet/Slider.vue";

import CodePreview from "./codePreview/index.vue";

import EntitySelect from "./entitySelect/index.vue";

const { proxy } = getCurrentInstance();
const state = reactive({
  curIndex: -1,
  rightActive: "form",
  componentsList: [
    {
      id: 1,
      name: "文字输入",
      type: "Input",
      value: "",
      labelText: "文字输入",
      placeholder: "请输入",
      disabled: false,
      isRequired: true,
      prop: "Input0",
      colSpan: 24,
      orderParam: {
        maxLength: 32,
        isClearable: false
      }
    },
    {
      id: 13,
      name: "数字输入",
      type: "InputNumber",
      value: null,
      labelText: "数字输入",
      placeholder: "请输入",
      disabled: false,
      isRequired: true,
      prop: "InputNumber0",
      colSpan: 24,
      orderParam: {
        maxLength: 10,
        isClearable: false
      }
    },
    {
      id: 2,
      name: "富文本域",
      type: "TextArea",
      value: "",
      labelText: "富文本域",
      placeholder: "请输入",
      disabled: false,
      isRequired: true,
      prop: "TextArea",
      colSpan: 24,
      orderParam: {
        maxLength: 200,
        isClearable: false
      }
    },
    {
      id: 3,
      name: "下拉单选",
      type: "SelectRadio",
      value: "",
      labelText: "下拉单选框",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "SelectRadio",
      colSpan: 24,
      orderParam: {
        isFilterable: false,
        isClearable: false
      }
    },
    {
      id: 4,
      name: "下拉多选",
      type: "SelectMultiple",
      value: [],
      labelText: "下拉多选框",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "SelectMultiple",
      colSpan: 24,
      orderParam: {
        isFilterable: false,
        isClearable: false
      }
    },
    {
      id: 5,
      name: "按钮单选",
      type: "ButtonRadio",
      value: null,
      labelText: "单选框",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "ButtonRadio",
      colSpan: 24,
      orderParam: {
        styleType: "default"
      }
    },
    {
      id: 6,
      name: "按钮多选",
      type: "ButtonCheckbox",
      value: [],
      labelText: "多选框",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "ButtonCheckbox",
      colSpan: 24,
      orderParam: {
        styleType: "default"
      }
    },
    {
      id: 7,
      name: "时间选择",
      type: "DatePicker",
      value: "",
      labelText: "时间框",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "DatePicker",
      colSpan: 24,
      orderParam: {
        styleType: "date"
      }
    },
    {
      id: 8,
      name: "起止日期",
      type: "DateRange",
      value: [],
      labelText: "起止日期",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "DateRange",
      colSpan: 24
    },
    {
      id: 9,
      name: "树形级联",
      type: "Cascader",
      value: [],
      labelText: "树形级联",
      placeholder: "请选择",
      disabled: false,
      isRequired: true,
      prop: "Cascader",
      colSpan: 24,
      orderParam: {
        isFilterable: true,
        isMultiple: false,
        isStrictly: false,
        isClearable: true
      }
    },
    {
      id: 10,
      name: "文件上传",
      type: "UploadFile",
      labelText: "上传",
      placeholder: "请选择",
      value: [],
      disabled: false,
      isRequired: true,
      prop: "UploadFile",
      colSpan: 24,
      orderParam: {
        accept: [
          ".xlsx",
          ".xls",
          ".doc",
          ".docx",
          ".ppt",
          ".pptx",
          ".pdf",
          ".png",
          ".jpg",
          ".mp4",
          ".mp3"
        ],
        maxLength: 5
      }
    },
    {
      id: 15,
      name: "图片上传",
      type: "UploadImage",
      labelText: "图片上传",
      placeholder: "请选择",
      value: [],
      disabled: false,
      isRequired: true,
      prop: "UploadImage",
      colSpan: 24,
      orderParam: {
        width: 100,
        maxLength: 5
      }
    },
    // {
    //   id: 11,
    //   name: "星星评分",
    //   type: "Rate",
    //   value: 0,
    //   labelText: "星星评分",
    //   placeholder: "请选择",
    //   disabled: false,
    //   isRequired: true,
    //   prop: "Rate",
    //   colSpan: 24,
    //   orderParam: {
    //     isText: false,
    //     texts: ["极差", "失望", "一般", "满意", "惊喜"]
    //   }
    // },
    {
      id: 12,
      name: "开关",
      type: "Switch",
      labelText: "开关",
      placeholder: "请选择",
      value: true,
      disabled: false,
      isRequired: true,
      prop: "Switch",
      colSpan: 24,
      orderParam: {
        activeText: "开",
        inactiveText: "关"
      }
    },
    {
      id: 14,
      name: "滑块拖动",
      type: "Slider",
      labelText: "滑块拖动",
      placeholder: "请选择",
      value: 5,
      disabled: false,
      isRequired: true,
      prop: "Slider",
      colSpan: 24,
      orderParam: {
        min: 1,
        max: 10,
        step: 1
      }
    }
  ],
  dataForm: {
    formParams: {
      size: "default",
      labelWidth: "100px",
      labelPosition: "top",
      isRequired: true,
      disabled: false
    },
    components: []
  },

  isCodePreview: false,
  isEntitySelect: false
});

const {
  dataForm,
  componentsList,
  curIndex,
  rightActive,
  isCodePreview,
  isEntitySelect
} = toRefs(state);

onMounted(() => {
  nextTick(() => {});
});

// 限制拖拽区域
function move(e) {
  const { to, from, draggedContext, relatedContext } = e;
  if (to && to.className == "drag-out-class") {
    return true;
  } else {
    if (relatedContext.index == null || relatedContext.index == undefined) {
      return true;
    }
    if (draggedContext.index == relatedContext.index) {
      return true;
    } else {
      return false;
    }
  }
}

// 拖拽完成
function add(e) {
  const { type, newIndex } = e;
  if (type == "add") {
    curIndex.value = newIndex;
  }
  rightActive.value = "component";
}

// 拖拽结束
function end(e) {
  const { type, newIndex } = e;
  if (type == "end") {
    curIndex.value = newIndex;
  }
}
// 拖起时刻
function choose(e) {
  const { type, oldIndex } = e;
  if (type == "choose") {
    curIndex.value = oldIndex;
  }
}

// 数据更新
function update(e) {
  dataForm.value.components.forEach((item, index) => {
    item.prop = item.type + index;
  });
  dataForm.value.components = JSON.parse(
    JSON.stringify(dataForm.value.components)
  );
}

// 表单 删除某一项
function handleDelete(index) {
  dataForm.value.components.splice(index, 1);
  rightActive.value = "form";
}
// 表单 点击某一项
function handleItem(index) {
  curIndex.value = index;
  rightActive.value = "component";
}

// 预览
function handlePreview() {
  if (!dataForm.value.components.length) {
    proxy.$modal.msgError(`请将'组件选择区'的组件拖拽到'页面展示区'`);
    return;
  }
  let flag = {
    name: ""
  };
  dataForm.value.components.forEach(item => {
    if (!/^[a-zA-Z]([-_a-zA-Z0-9]{2,20})$/.test(item.prop)) {
      flag = item;
    }
  });
  if (flag.name) {
    proxy.$modal.msgError(`${flag.name} : 表单项Key填写错误`);
    return;
  }

  isCodePreview.value = true;
  proxy.$nextTick(() => {
    proxy.$refs["CodePreviewRef"].init(dataForm.value);
  });
}

// 选择表
function entitySelect(data) {
  let newArr = [];
  componentsList.value.forEach(item =>  {
      data.forEach(ele => {
        if(item.type == ele.type) {
            item.prop = ele.prop;
            item.labelText = ele.labelText;
            item.isRequired = ele.required;
            newArr.push(item);
        }
      })
    } 
  );
  console.log("newArr", newArr);
  dataForm.value = {
    formParams: {
      size: "default",
      labelWidth: "100px",
      labelPosition: "top",
      isRequired: true,
      disabled: false
    },
    components: newArr
  };
}

// 生成
function handleCreate() {
  console.log("生成");
}

// 导入
function handleImport() {
  console.log("导入");
  // proxy.$modal.msgError("开发中");
  isEntitySelect.value = true;
  proxy.$nextTick(() => {
    proxy.$refs["EntitySelectRef"].init();
  });
}
</script>
<style lang="scss" scoped>
.app-container {
  display: flex;
  height: 100%;
  overflow: hidden;
  box-sizing: border-box;
  // background: #ccc;
  padding: 15px;
  .left-box {
    width: 340px;
    flex: none;
    .parent-flex {
      display: flex;
      flex-wrap: wrap;
      .componentsItem {
        width: 100px;
        text-align: center;
        padding: 20px;
        margin: 0 15px 15px 0;
        border-radius: 6px;
        cursor: pointer;
        color: #a5a7b2;
        box-shadow: 0 0 5px #ccc;
      }
    }
  }
  .content-box {
    flex: 1;
    overflow: hidden;
    height: 100%;
    display: flex;
    flex-direction: column;
    :deep(.el-scrollbar__view) {
      height: 100%;
    }
    .layout {
      flex: 1;
      height: 100%;
      // overflow: hidden;
      background: #f9f9f9;
      border-radius: 5px;
      box-sizing: border-box;
      padding: 15px;
      .drag-out-class {
        min-height: 400px;
        width: 100%;
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
        .move {
          border-color: #ec1c24;
        }
      }
      .colSpan {
        height: min-content;
        border: 1px dashed #dcdada;
        padding: 20px;
        margin-bottom: 10px;
        position: relative;
        cursor: move;
        .deleteBtn {
          position: absolute;
          right: 5px;
          top: 0;
          cursor: pointer;
          color: #ec1c24;
          font-size: 12px;
          /* font-weight: 700; */
        }
        .deleteBtn:hover {
          color: #fff;
          background: #ec1c24;
          padding: 0 10px;
          border-radius: 5px;
        }
      }
    }
    .btns {
      padding: 15px;
      justify-content: center;
      display: flex;
      flex: none;
    }
  }
  .right-box {
    width: 400px;
    flex: none;
    box-sizing: border-box;
    padding-left: 40px;
  }
}
</style>
